import 'package:flutter/material.dart';

/// Dart空安全示例
class NullSafetyExample extends StatefulWidget {
  const NullSafetyExample({super.key});

  @override
  State<NullSafetyExample> createState() => _NullSafetyExampleState();
}

class _NullSafetyExampleState extends State<NullSafetyExample> {
  String result = '点击下方按钮查看空安全示例';

  void _demonstrateNullableTypes() {
    // 非空类型
    String name = 'Alice';
    // name = null; // ✗ 错误：不能赋值为null

    // 可空类型
    String? nullableName = 'Bob';
    nullableName = null; // ✓ 可以

    int? age;
    // int value = age; // ✗ 错误：age可能为null

    setState(() {
      result =
          '''
【可空类型 (?)】

1. 非空类型（默认）:
String name = 'Alice';
name = null; // ✗ 错误：不能为null

2. 可空类型（添加?）:
String? nullableName = 'Bob';
nullableName = null; // ✓ 可以

3. 未初始化的可空类型自动为null:
String? name; // 自动为null
int? age;     // 自动为null

示例:
String name = 'Alice';      // 非空
String? maybeName = null;   // 可空
int? maybeAge;              // 可空，默认null

类型系统保证:
• 非空类型永远不会是null
• 编译时检查，避免空指针错误
• 需要显式处理null情况

当前演示:
name = $name (非空)
nullableName = $nullableName (可空)
age = $age (可空，未赋值)
      ''';
    });
  }

  void _demonstrateNullAwareOperators() {
    String? name;
    String? email = 'user@example.com';

    // ?? 空值合并运算符
    String displayName = name ?? 'Guest';

    // ??= 空值赋值运算符
    name ??= 'Default Name';

    // ?. 条件访问运算符
    int? length = email?.length;

    setState(() {
      result =
          '''
【空值感知运算符】

1. ?? (空值合并运算符)
   如果左边为null，使用右边的值
   
   String? name;
   String displayName = name ?? 'Guest';
   结果: $displayName

2. ??= (空值赋值运算符)
   只有当变量为null时才赋值
   
   String? name;
   name ??= 'Default Name';
   结果: $name

3. ?. (条件访问运算符)
   只有非null时才访问成员
   
   String? email = 'user@example.com';
   int? length = email?.length;
   结果: $length
   
   String? nullEmail;
   int? nullLength = nullEmail?.length;
   结果: null（不会抛出错误）

4. 链式调用:
   String? result = user?.address?.street?.name;
   
   如果链条中任何一个为null，整个表达式返回null

实际应用:
// 获取用户名，如果为null显示Guest
Text(user?.name ?? 'Guest')

// 只有email不为null才显示
if (email?.isNotEmpty ?? false) {
  print(email);
}
      ''';
    });
  }

  void _demonstrateNullAssertionOperator() {
    String? name = 'Alice';

    // ! 断言运算符：告诉编译器这里肯定不是null
    String definitelyName = name!;

    setState(() {
      result =
          '''
【! 断言运算符】
当你确定值不为null时，使用!强制转换为非空类型。

String? name = 'Alice';
String definitelyName = name!; // 断言name不为null

结果: $definitelyName

⚠️ 注意:
如果值实际上是null，会抛出运行时错误！

String? nullName = null;
String bad = nullName!; // 💥 运行时错误！

使用场景:
1. 你确定值不会是null
2. 在null检查之后

if (name != null) {
  String safe = name!; // 这里安全
}

3. 从map获取已知存在的值
Map<String, String> config = {'key': 'value'};
String value = config['key']!;

最佳实践:
• 尽量少用! 
• 优先使用 ?? 或 ?.
• 只在确定不为null时使用
• 考虑在使用前先检查null

避免:
widget.data!.name!.value! // 💀 危险！

推荐:
widget.data?.name?.value ?? 'default' // ✓ 安全
      ''';
    });
  }

  void _demonstrateLateKeyword() {
    setState(() {
      result = '''
【late 关键字】
延迟初始化非空变量。

1. 稍后初始化:
late String description;

void init() {
  description = 'Initialized'; // 在使用前赋值
}

2. 延迟计算:
late String expensiveValue = computeExpensive();
// computeExpensive() 只在首次访问时调用

3. 非空保证:
class User {
  late String name; // 不是可空的，但稍后赋值
  
  User() {
    // name = loadName(); // 必须在使用前赋值
  }
}

⚠️ 注意:
• 使用前必须赋值，否则运行时错误
• late变量可以被多次赋值（除非是final）

late final String config = loadConfig();
// config 只能赋值一次，且延迟加载

Flutter中的应用:
class _MyWidgetState extends State<MyWidget> {
  late AnimationController _controller;
  
  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 1),
    );
  }
}

late vs 可空类型:
┌──────────────┬────────────────┐
│ String? name │ 可以是null     │
│              │ 需要处理null   │
├──────────────┼────────────────┤
│ late String  │ 延迟初始化     │
│     name     │ 不能是null     │
│              │ 使用前必须赋值 │
└──────────────┴────────────────┘
      ''';
    });
  }

  void _demonstrateNullChecks() {
    String? email = 'user@example.com';

    setState(() {
      result =
          '''
【Null检查最佳实践】

1. 类型提升（Type Promotion）:
String? email = getEmail();

if (email != null) {
  // 这里email自动提升为String（非空）
  print(email.length); // 不需要!或?.
}

2. 提前返回:
String? validateEmail(String? email) {
  if (email == null) return 'Email不能为空';
  if (email.isEmpty) return 'Email不能为空字符串';
  if (!email.contains('@')) return 'Email格式错误';
  return null; // 验证通过
}

3. 使用 ?? 提供默认值:
String name = user?.name ?? 'Guest';
int age = user?.age ?? 0;

4. 使用 ?. 安全访问:
int? length = user?.email?.length;

5. 集合的null安全:
List<String>? names = getNames();

// 如果names为null，使用空列表
for (var name in names ?? []) {
  print(name);
}

// 或使用 ?.
names?.forEach((name) => print(name));

6. 断言处理:
void process(String? data) {
  assert(data != null, 'data不能为null');
  // ... 使用data
}

7. 空值合并级联:
String result = name ?? email ?? phone ?? 'Unknown';

实际示例:
当前email: $email
长度: ${email?.length}
是否有效: ${email?.contains('@') ?? false}
显示名: ${email ?? '未提供'}

推荐模式:
✓ if (value != null) { use(value); }
✓ value?.method()
✓ value ?? defaultValue
✗ value! (尽量避免)
      ''';
    });
  }

  void _demonstrateNullSafetySummary() {
    setState(() {
      result = '''
【空安全总结】

Dart空安全核心概念:
┌──────────────┬───────────────────┐
│ 符号         │ 含义              │
├──────────────┼───────────────────┤
│ T            │ 非空类型          │
│ T?           │ 可空类型          │
│ !            │ 断言非空          │
│ ?.           │ 条件访问          │
│ ??           │ 空值合并          │
│ ??=          │ 空值赋值          │
│ late         │ 延迟初始化        │
│ required     │ 必需参数          │
└──────────────┴───────────────────┘

类型对比:
String name;              // 非空，必须初始化
String? name;             // 可空，可以是null
late String name;         // 延迟初始化，非空
late String? name;        // 延迟初始化，可空
final String name;        // 非空常量
final String? name;       // 可空常量

常见模式:

1. 可选参数:
void greet({String? name}) {
  print('Hello, \${name ?? "Guest"}');
}

2. 可选返回值:
String? findUser(int id) {
  return users[id]; // 可能不存在
}

3. 必需参数:
class User {
  User({required this.name, this.age});
  final String name;  // 必需
  final int? age;     // 可选
}

4. 空值处理:
// 提供默认值
String name = user?.name ?? 'Unknown';

// 提前返回
if (user == null) return;

// 条件执行
user?.save();

迁移到空安全的好处:
• ✓ 消除空指针异常
• ✓ 编译时发现问题
• ✓ 代码更健壮
• ✓ 性能更好
• ✓ IDE更好的提示

记住:
• 默认非空，需要可空才加?
• 尽量避免使用!
• 利用类型提升
• 使用??提供默认值
      ''';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Dart 空安全'), backgroundColor: Theme.of(context).colorScheme.inversePrimary),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // 说明卡片
            Card(
              color: Colors.lightBlue.shade50,
              child: const Padding(
                padding: EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('🛡️ 空安全概述', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                    SizedBox(height: 8),
                    Text(
                      'Dart的空安全系统消除空指针错误：\n'
                      '• ?: 可空类型标记\n'
                      '• !: 断言非空\n'
                      '• ?.: 条件访问\n'
                      '• ??: 空值合并\n'
                      '• late: 延迟初始化',
                      style: TextStyle(fontSize: 14),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),

            // 代码示例区域
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(color: Colors.grey.shade200, borderRadius: BorderRadius.circular(8)),
              child: const Text('''// 可空类型
String name;      // 非空
String? name;     // 可空

// 空值感知运算符
name ?? 'Guest'   // 空值合并
name ??= 'Bob'    // 空值赋值
name?.length      // 条件访问
name!             // 断言非空

// 延迟初始化
late String data;

// 必需参数
User({required this.name});''', style: TextStyle(fontFamily: 'monospace', fontSize: 13)),
            ),
            const SizedBox(height: 16),

            // 交互按钮
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton.icon(
                  onPressed: _demonstrateNullableTypes,
                  icon: const Icon(Icons.question_mark),
                  label: const Text('可空类型 ?'),
                ),
                ElevatedButton.icon(
                  onPressed: _demonstrateNullAwareOperators,
                  icon: const Icon(Icons.merge_type),
                  label: const Text('?? ?. ??='),
                ),
                ElevatedButton.icon(
                  onPressed: _demonstrateNullAssertionOperator,
                  icon: const Icon(Icons.error_outline),
                  label: const Text('断言 !'),
                ),
                ElevatedButton.icon(onPressed: _demonstrateLateKeyword, icon: const Icon(Icons.schedule), label: const Text('late')),
                ElevatedButton.icon(onPressed: _demonstrateNullChecks, icon: const Icon(Icons.check_circle), label: const Text('Null检查')),
                ElevatedButton.icon(onPressed: _demonstrateNullSafetySummary, icon: const Icon(Icons.summarize), label: const Text('总结')),
              ],
            ),
            const SizedBox(height: 16),

            // 结果展示区域
            Card(
              elevation: 4,
              child: Container(
                width: double.infinity,
                padding: const EdgeInsets.all(16),
                constraints: const BoxConstraints(minHeight: 150),
                child: Text(result, style: const TextStyle(fontSize: 14, fontFamily: 'monospace')),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
